// Copyright (C) 2025, ZWSOFT Co., LTD.(Guangzhou)
// Licensed under the MIT License. See LICENSE in the project root for license information.

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TestClient.Domain;

namespace TestClient.ViewModel
{
    public partial class PointInquireTestViewModel : PageViewModelBase
    {
        public IAsyncRelayCommand SelectPointCommand { get; }
        public IAsyncRelayCommand SelectCurveCommand { get; }
        public IAsyncRelayCommand SelectSurfaceCommand { get; }
        public IAsyncRelayCommand InquirePointCurveRelationCommand { get; }
        public IAsyncRelayCommand InquirePointSurfaceRelationCommand { get; }
        public IAsyncRelayCommand InquireCoordinateSurfaceRelationCommand { get; }
        public IAsyncRelayCommand InquireWithBoundaryCommand { get; }

        [ObservableProperty]
        private string pointId = "";
        [ObservableProperty]
        private string curveId = "";
        [ObservableProperty]
        private string surfaceId = "";
        [ObservableProperty]
        private double coordX;
        [ObservableProperty]
        private double coordY;
        [ObservableProperty]
        private double coordZ;

        [ObservableProperty]
        private string pointRelativePos = "";

        public PointInquireTestViewModel(
            VFAdapterWrapper wrapper,
            ISnackNotifyService notifyService
        ) : base(wrapper, notifyService)
        {
            SelectPointCommand = CreateAsyncRpcCommand(SelectPoint);
            SelectCurveCommand = CreateAsyncRpcCommand(SelectCurve);
            SelectSurfaceCommand = CreateAsyncRpcCommand(SelectSurface);
            InquirePointCurveRelationCommand = CreateAsyncRpcCommand(InquirePointCurveRelation);
            InquirePointSurfaceRelationCommand = CreateAsyncRpcCommand(InquirePointSurfaceRelation);
            InquireCoordinateSurfaceRelationCommand = CreateAsyncRpcCommand(InquireCoordinateSurfaceRelation);
            InquireWithBoundaryCommand = CreateAsyncRpcCommand(InquireWithBoundary);
        }

        private async Task SelectPoint()
        {
            EnsureConnected();
            PointId = await ViewModelHelpers.SelectEnt(Wrapper, "Point");
        }

        private async Task SelectCurve()
        {
            EnsureConnected();
            CurveId = await ViewModelHelpers.SelectEnt(Wrapper, "Curve");
        }

        private async Task SelectSurface()
        {
            EnsureConnected();
            SurfaceId = await ViewModelHelpers.SelectEnt(Wrapper, "Surface");
        }

        private async Task InquirePointCurveRelation()
        {
            EnsureConnected();
            bool isOn = await Task.Run(() =>
            {
                return Wrapper.TestPointOnCurve(PointId, CurveId);
            });

            PointRelativePos = isOn switch
            {
                true => "Point on curve",
                false => "Point not on curve"
            };

        }

        private async Task InquirePointSurfaceRelation()
        {
            EnsureConnected();
            var relation = await Task.Run(() =>
            {
                return Wrapper.TestPointOnSurface(PointId, SurfaceId);
            });

            PointRelativePos = relation switch
            {
                0 => "Outside surface",
                1 => "Inside surface",
                2 => "Boundary",
                _ => "Unknown",
            };

        }

        private async Task InquireCoordinateSurfaceRelation()
        {
            EnsureConnected();
            var point = new Vector3d { x = CoordX, y = CoordY, z = CoordZ };
            var relation = await Task.Run(() =>
            {
                return Wrapper.TestPointOnSurface(point, SurfaceId);
            });

            PointRelativePos = relation switch
            {
                0 => "Outside surface",
                1 => "Inside surface",
                2 => "Boundary",
                _ => "Unknown",
            };
        }

        private async Task InquireWithBoundary()
        {
            EnsureConnected();
            var relation = await Task.Run(() =>
            {
                var point = Wrapper.GetPointCoord(PointId);
                return Wrapper.TestPointAndBoundary(CurveId, SurfaceId, point);
            });

            PointRelativePos = relation switch
            {
                0 => "Outside surface",
                1 => "Inside surface",
                2 => "Boundary",
                _ => "Unknown",
            };
        }
    }
}
